﻿using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium.Support;
using OpenQA.Selenium.Support.UI;

namespace Fluent.Light.Elements
{
    public class WebElement : IWebElement
    {
        private IWebDriver _driver { get; set; }
        private By _by { get; set; }
        private IWebElement _element
        {
            get
            {
                if (!Exists)
                {
                    throw new NoSuchElementException();
                }

                return _driver.FindElement(_by);
            }
        }

        public WebElement(IWebDriver driver, By by)
        {
            this._by = by;
            this._driver = driver;
        }

        public IWebElement this[int index]
        {
            get
            {
                return _driver.FindElements(_by)[index];
            }
        }

        public string this[string htmlAttributeName]
        {
            get
            {
                return _element.GetAttribute(htmlAttributeName);
            }
        }

        #region Properties
        
        public string TagName
        {
            get { return _element.TagName; }
        }

        public string Text
        {
            get { return _element.Text; }
        }

        public string OutHTML
        {
            get { return this[HtmlAttributesConst.OUTHTML]; }
        }

        public string InnerHTML
        {
            get { return this[HtmlAttributesConst.INNERHTML]; }
        }

        public string ID
        {
            get { return this[HtmlAttributesConst.ID]; }
        }

        public string Name
        {
            get { return this[HtmlAttributesConst.NAME]; }
        }

        public string ClassName
        {
            get { return this[HtmlAttributesConst.CLASS]; }
        }

        public string Value
        {
            get { return this[HtmlAttributesConst.VALUE]; }
        }

        public int X
        {
            get { return Location.X; }
        }

        public int Y
        {
            get { return Location.Y; }
        }

        public string Width
        {
            get { return GetCssValue(HtmlAttributesConst.WIDTH); }
        }

        public string Height
        {
            get { return GetCssValue(HtmlAttributesConst.HEIGHT); }
        }

        public Point Location
        {
            get { return _element.Location; }
        }

        public Size Size
        {
            get { return _element.Size; }
        }

        #endregion

        #region States

        public bool Displayed
        {
            get { return _element.Displayed; }
        }

        public bool Enabled
        {
            get { return _element.Enabled; }
        }

        public bool Selected
        {
            get { return _element.Selected; }
        }

        public bool Exists
        {
            get
            {
                return _driver.Wait(webdriver =>
                {
                    return _driver.FindElements(_by).Count > 0;
                }, 5000);
            }
        }

        #endregion

        #region Actions
        
        public void Clear()
        {
            _element.Clear();
        }

        public void Click()
        {
            _element.Click();
        }

        public void SendKeys(string text)
        {
            _element.SendKeys(text);
        }
        
        public void Submit()
        {
            _element.Submit();
        }

        #endregion

        public string GetAttribute(string attributeName)
        {
            return _element.GetAttribute(attributeName);
        }

        public string GetCssValue(string propertyName)
        {
            return _element.GetCssValue(propertyName);
        }

        public IWebElement FindElement(By by)
        {
            return _element.FindElement(by);
        }

        public ReadOnlyCollection<IWebElement> FindElements(By by)
        {
            return _element.FindElements(by);
        }
    }
}
